<?php

namespace yak\layui\widgets\grid;

use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
use yii\data\ActiveDataProvider;
use yii\i18n\Formatter;

/**
 * Class LayuiListData
 * @package yak\layui\widgets\tables
 */
class LayuiListData extends Component
{
    /**
     * @var array
     */
    public $columns;

    /**
     * @var ActiveDataProvider
     */
    public $dataProvider;

    /**
     * @var array|Formatter
     */
    public $formatter;

    public function init()
    {
        if ($this->formatter === null) {
            $this->formatter = Yii::$app->getFormatter();
        } elseif (is_array($this->formatter)) {
            $this->formatter = Yii::createObject($this->formatter);
        }
        if (!$this->formatter instanceof Formatter) {
            throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
        }

        $this->initColumns();
    }

    protected function initColumns()
    {
        if (empty($this->columns)) {
            $this->guessColumns();
        }
        foreach ($this->columns as $i => $column) {
            if (is_string($column)) {
                $column = $this->createDataColumn($column);
            } else {
                $column = Yii::createObject(array_merge([
                    'class' => DataColumn::className(),
                    'grid' => $this,
                ], $column));
            }
            if (!$column->visible) {
                unset($this->columns[$i]);
                continue;
            }
            $this->columns[$i] = $column;
        }
    }

    /**
     * This function tries to guess the columns to show from the given data
     * if [[columns]] are not explicitly specified.
     */
    protected function guessColumns()
    {
        $models = $this->dataProvider->getModels();
        $model = reset($models);
        if (is_array($model) || is_object($model)) {
            foreach ($model as $name => $value) {
                if ($value === null || is_scalar($value) || is_callable([$value, '__toString'])) {
                    $this->columns[] = (string)$name;
                }
            }
        }
    }

    /**
     * @param $text
     * @return object|DataColumn
     * @throws InvalidConfigException
     */
    protected function createDataColumn($text)
    {
        if (!preg_match('/^([^:]+)(:(\w*))?(:(.*))?$/', $text, $matches)) {
            throw new InvalidConfigException('The column must be specified in the format of "attribute", "attribute:format" or "attribute:format:label"');
        }

        return Yii::createObject([
            'class' => DataColumn::className(),
            'grid' => $this,
            'attribute' => $matches[1],
            'format' => isset($matches[3]) ? $matches[3] : 'text',
            'label' => isset($matches[5]) ? $matches[5] : null,
        ]);
    }

    public function renderData()
    {
        $models = array_values($this->dataProvider->getModels());
        $keys = $this->dataProvider->getKeys();
        $data = [];
        foreach ($models as $index => $model) {
            $key = $keys[$index];
            $data[] = $this->renderRow($model, $key, $index);
        }

        return $data;
    }

    protected function renderRow($model, $key, $index)
    {
        $cells = [];
        /* @var $column DataColumn */
        foreach ($this->columns as $column) {

            if (!$column->hasProperty('attribute')) {
                continue;
            }

            $attribute = $column->attribute;
            $cells[$attribute] = $column->renderDataCell($model, $key, $index);
        }
        return $cells;
    }

    public function renderHeader()
    {
        $header = [];
        /* @var $column DataColumn */
        foreach ($this->columns as $column) {

            if (!$column->hasProperty('attribute')) {
                continue;
            }

            $attribute = $column->attribute;
            $header[$attribute] = $column->getLabel();
        }
        return $header;
    }
}